﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PACKETPARSERMAX20.CORE;

namespace PACKETPARSERMAX20.CONSOLE
{
    public static class FindOpcodeInLog
    {
        public static void ProcessSource(string source)
        {
            using (var sw = new System.IO.StreamWriter("dump.log", false))
            {
                string[] files = System.IO.Directory.GetFiles(source, "*.sqlite", System.IO.SearchOption.AllDirectories);

                foreach (string file in files)
                {
                    var sb = ProcessFile(file);

                    if (sb.Length > 0)
                    {
                        sw.Write(sb.ToString());
                    }
                }
            }
        }

        public static StringBuilder ProcessFile(string file)
        {
            var sblog = new StringBuilder();

            var tOpcodesToFind = new List<uint>();

            //var db = new PACKETPARSERMAX20.CORE.DBCDatabase("dbc_333", true);
            //var table = db.ExecuteGetDataTable("select id, field6, map_type, name from map");


            //PACKETPARSERMAX20.CORE.SQL.CUSTOM.DBCMap.MapList = new List<CORE.SQL.CUSTOM.DBCMap>();

            //foreach (System.Data.DataRow row in table.Rows)
            //{
            //    PACKETPARSERMAX20.CORE.SQL.CUSTOM.DBCMap.MapList.Add(new CORE.SQL.CUSTOM.DBCMap() { id = row["id"].GetIntOrZero(), map_type = row["map_type"].GetIntOrZero(), name = row["name"].GetStringOrEmpty(), name_internal = row["field6"].GetStringOrEmpty() });

            //}
            //PACKETPARSERMAX20.CORE.SQL.CUSTOM.DBCMap.SaveDBCMapList();

            // tOpcodesToFind.Add((uint)Opcodes.CMSG_INSTANCE_LOCK_WARNING_RESPONSE);
            //tOpcodesToFind.Add((uint)Opcodes.SMSG_INSTANCE_LOCK_WARNING_QUERY);
            //tOpcodesToFind.Add((uint)Opcodes.CMSG_SET_SAVED_INSTANCE_EXTEND);
            // tOpcodesToFind.Add((uint)Opcodes.SMSG_INSTANCE_SAVE_CREATED);
            //tOpcodesToFind.Add((uint)Opcodes.SMSG_RAID_INSTANCE_INFO);
            tOpcodesToFind.Add((uint)Opcodes.SMSG_RAID_INSTANCE_MESSAGE);
            // tOpcodesToFind.Add((uint)Opcodes.CMSG_RESET_INSTANCES);
            //tOpcodesToFind.Add((uint)Opcodes.SMSG_INSTANCE_RESET);
            //tOpcodesToFind.Add((uint)Opcodes.SMSG_INSTANCE_RESET_FAILED);
            //tOpcodesToFind.Add((uint)Opcodes.SMSG_UPDATE_LAST_INSTANCE);
            //tOpcodesToFind.Add((uint)Opcodes.SMSG_UPDATE_INSTANCE_OWNERSHIP);
            //tOpcodesToFind.Add((uint)Opcodes.SMSG_INSTANCE_DIFFICULTY);
            //tOpcodesToFind.Add((uint)Opcodes.MSG_GM_RESETINSTANCELIMIT);
            //tOpcodesToFind.Add((uint)Opcodes.CMSG_COMMENTATOR_ENTER_INSTANCE);
            //tOpcodesToFind.Add((uint)Opcodes.CMSG_COMMENTATOR_EXIT_INSTANCE);
            //tOpcodesToFind.Add((uint)Opcodes.CMSG_COMMENTATOR_INSTANCE_COMMAND);
            // tOpcodesToFind.Add((uint)Opcodes.CMSG_EXPIRE_RAID_INSTANCE);
            // tOpcodesToFind.Add((uint)Opcodes.SMSG_CORPSE_IS_NOT_IN_INSTANCE);
            // tOpcodesToFind.Add((uint)Opcodes.MSG_SET_DUNGEON_DIFFICULTY);
            //tOpcodesToFind.Add((uint)Opcodes.SMSG_LFG_QUEUE_STATUS);
            // tOpcodesToFind.Add((uint)Opcodes.SMSG_LFG_OPEN_FROM_GOSSIP);

            var sb = new StringBuilder();
            foreach (var opcode in tOpcodesToFind)
            {

                sb.Append(opcode);
                if (tOpcodesToFind.IndexOf(opcode) != tOpcodesToFind.Count - 1) sb.Append(",");

            }
            var tOpcodeFilterSql = string.Format(" opcode IN ( {0} )", sb);


            var eventManager = new EventManager();
            var opcodeFilter = new OpcodeFilter();

            var processor = DefinitionProcessor.LoadDefinitionProcessor(file, eventManager, opcodeFilter);
            if (processor != null)
            {
                int build = processor.Reader.ClientBuild;
                processor.Reader.MaxProcessCount = 5000000;

                string query = string.Format("{0} {1}", "WHERE", tOpcodeFilterSql);

                int count = processor.Reader.GetTotalByQuery(query);
                if (count > 0)
                {
                    sblog.AppendLine(string.Format("{0} {1}", file, build));
                    query = string.Format("{0} {1}", "AND", tOpcodeFilterSql);
                    // processor.reader
                    processor.Reader.Load(query);

                    var tList = new List<string>();
                    while (true)
                    {
                        var tPacket = processor.Reader.GetNextPacket();

                        if (tPacket == null) break;

                        var context = new DefinitionContext(tPacket, processor.Reader, processor.Core, processor.DefinedOpcodeList);
                        var def = context.GetDefinition();
                        def.Process();
                        if (!tList.Contains(def.Result))
                        {
                            tList.Add(def.Result);
                            sblog.AppendLine("----------------------------------");
                            sblog.AppendLine("\t" + tPacket.OpcodeName + ":");
                            sblog.AppendLine("\t\t" + def.Result.Replace("\n", "\n\t\t"));
                            sblog.AppendLine("----------------------------------");
                        }
                    }



                    System.Console.WriteLine(string.Format("{0} {1} \n {2}", file, build, sblog));
                }
            }

            return sblog;
        }
    }
}
